package main

import (
	"fmt"
	"strconv"
)

func main() {
	// 字符串 Strings
	s1 := "Hello" + "World"
	fmt.Println(s1)
	s2 := `A "raw" string literal
can include line breaks.`
	fmt.Println(s2)

	fmt.Println(len(s1))
	fmt.Println(s1[0:5])

	//数字 Numbers
	num := 3 // int
	fmt.Println(num)
	num1 := 3. // float64
	fmt.Println(num1)
	num2 := 3 + 4i // complex128
	fmt.Println(num2)
	num3 := byte('A') // byte (alias: uint8)
	fmt.Print(num3)
	var num4 uint = 7 // uint (unsigned)
	fmt.Println(num4)
	var num5 float32 = 22.7 // 32-bit float
	fmt.Println(num5)
	x := 5
	x++
	fmt.Println("x + 4 =", x+4)
	fmt.Println("x * 4 =", x*4)

	// 布尔值 Booleans
	isTrue := true
	isFalse := false

	fmt.Println(isTrue)
	fmt.Println(isFalse)

	fmt.Println(true && true)  // true
	fmt.Println(true && false) // false
	fmt.Println(true || true)  // true
	fmt.Println(true || false) // true
	fmt.Println(!true)         // false

	// 数组 Arrays
	primes := []int{2, 3, 5, 7, 11, 13}
	fmt.Println(len(primes))
	fmt.Println(primes)
	// 与 [:3] 相同，输出：[2 3 5]
	fmt.Println(primes[0:3])
	var a [2]string
	a[0] = "Hello"
	a[1] = " World!"
	fmt.Println(a[0], a[1])
	fmt.Println(a)

	var twoDemension [2][3]int
	for i := 0; i < 2; i++ {
		for j := 0; j < 3; j++ {
			twoDemension[i][j] = i + j
		}
	}
	// => 2d:  [[0 1 2] [1 2 3]]
	fmt.Println("2d: ", twoDemension)

	//指针(Pointers)
	b := *getPointer()
	fmt.Println("Value is", b)

	// var p *int
	// *p = 123 // panic   nil pointer
	//有一块内存存放了10，它的地址由系统自动分配，别名是c
	c := 10
	//内存存放的10变成了20
	c = 20
	var p *int
	p = &c
	//上面的p是一个指针，通过 *p 的方式同样可以访问 变量a指向 的内存
	fmt.Println("Value is", c)
	fmt.Println("Value is", p)
	fmt.Println("Value is", *p)
	*p = 30
	fmt.Println("Value is", c)

	/*当你动态申请内存的时候，指针的存在意义之一就被体现出来了*/
	ptr := new(int)
	//申请了一块内存空间，没有办法指定别名，new()返回内存地址，用指针接收
	//此时并没有变量能直接指向这块内存，所以只能通过内存地址来访问
	fmt.Println("Value is", *ptr)
	*ptr = 100
	fmt.Println("Value is", *ptr)

	//切片(Slices)
	//切片是对数组的抽象
	s := make([]string, 3)
	s[0] = "a"
	s[1] = "b"
	s = append(s, "d")
	s = append(s, "e", "f")
	fmt.Println("s is", s)
	fmt.Println(s[1])
	fmt.Println(len(s))
	fmt.Println(s[1:3])

	// 常量(Constants)
	const s3 string = "constant"
	const Phi = 1.618
	const n = 500000000
	const d = 3e20 / n
	// 常量声明可以使用 iota常量生成器 初始化，它用于 生成一组以相似规则初始化的常量，但是不用每行都 写一遍初始化表达式
	const (
		a1 = iota
		b1
		c1
	)
	fmt.Println(c1)

	// 类型转换
	i := 90
	f := float64(i)
	u := uint(i)
	// 将等于字符Z
	s4 := string(i)
	fmt.Println(f, u, s4)
	s5 := strconv.Itoa(i)
	fmt.Println(s5) // Outputs: 90
}

func getPointer() (myPointer *int) {
	a := 234
	return &a
}
